package org.grayrabbit.cms.publish.service.impl;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.util.List;

import org.grayrabbit.cms.constant.ConstantTheme;
import org.grayrabbit.cms.entity.Admin;
import org.grayrabbit.cms.entity.Category;
import org.grayrabbit.cms.entity.Content;
import org.grayrabbit.cms.entity.PublishLog;
import org.grayrabbit.cms.entity.PublishTask;
import org.grayrabbit.cms.entity.Site;
import org.grayrabbit.cms.entity.Survey;
import org.grayrabbit.cms.entity.Topic;
import org.grayrabbit.cms.freemarker.tpl.config.PopulateFtlData;
import org.grayrabbit.cms.publish.api.Generatable;
import org.grayrabbit.cms.publish.generate.Generater;
import org.grayrabbit.cms.publish.generate.factory.AbstractFactory;
import org.grayrabbit.cms.publish.generate.factory.GeneraterFactory;
import org.grayrabbit.cms.publish.generate.factory.GeneraterFactoryImpl;
import org.grayrabbit.cms.service.category.CategoryService;
import org.grayrabbit.cms.service.content.ContentService;
import org.grayrabbit.cms.service.plugins.SurveyService;
import org.grayrabbit.cms.service.publish.PublishLogService;
import org.grayrabbit.cms.service.publish.PublishTaskService;
import org.grayrabbit.cms.service.site.SiteService;
import org.grayrabbit.cms.service.topic.TopicService;
import org.grayrabbit.cms.util.FilePathSptUtil;
import org.grayrabbit.cms.vo.content.ContentBean;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import freemarker.template.Configuration;
import freemarker.template.DefaultObjectWrapper;
@Service
@Transactional
public class DefaultGenerator implements Generatable {
	private  static Logger log = LoggerFactory.getLogger(DefaultGenerator.class);
	@Autowired
	private ApplicationContext applicationContext;
	@Autowired
	@Qualifier("contentServiceImpl")
	private ContentService contentService;
	@Autowired
	@Qualifier("siteServiceImpl")
	private SiteService siteService;
	@Autowired
	@Qualifier("freemarkerConfiguration")
	private Configuration config;
	
	private static boolean configed = false;
	@Autowired
	@Qualifier("categoryServiceImpl")
	private CategoryService categoryService;
	@Autowired
	@Qualifier("topicServiceImpl")
	private TopicService topicService;
	@Autowired
	@Qualifier("surveyServiceImpl")
	private SurveyService surveyService;
	@Autowired
	@Qualifier("publishLogServiceImpl")
	private PublishLogService publishLogService;
	
	@Autowired
	@Qualifier("publishTaskServiceImpl")
	private PublishTaskService publishTaskService;
	
	@Transactional(noRollbackFor=RuntimeException.class)
	public void genreate(Admin admin,Site site, String genType, List<String> targets,int pageSize, int pageNum,PublishTask publishTask) throws Exception {
		createGenerater(admin,site,genType,targets,pageSize,pageNum).genFile(publishTask); 
	}
	
	private Generater createGenerater(Admin admin,Site site,String genType,List<String> targets,int pageSize,int pageNum) throws Exception {
		AbstractFactory factory = new GeneraterFactoryImpl(getConfig(),
				genType, 
				targets,
				ConstantTheme.THEME, 
				site, 
				pageSize, 
				pageNum,
				this,
				admin);
		GeneraterFactory gFactory = factory.getGeneraterFactory();
		return gFactory.create();
	}

	private Configuration getConfig(){
		if(!configed){
			synchronized (DefaultGenerator.class) {
				String realThemeRootpath =  FilePathSptUtil.THEME_ROOT_PATH+ConstantTheme.THEME;
				try {
					config.setDirectoryForTemplateLoading(new File(realThemeRootpath));
					log.debug("spring applicationContext is {}",applicationContext);
					PopulateFtlData.initFreemarkerConfiguration(applicationContext,config);
				} catch (IOException e) {
					log.error("设置Freemaker的theme路径时出错了.",e);
				}
				config.setObjectWrapper(new DefaultObjectWrapper());
				configed = true;
			}
		}
			return config;
	}
	public ByteArrayOutputStream preview(Site site,String genType,List<String> targetIds,Admin currentAdmin) throws Exception {
		return createGenerater(currentAdmin,site,genType,targetIds,0,0).getStream();
	}
	public List<String> findCatIdsBySiteId(List<String> siteIds,int currentCatIndex, int max) {
		return categoryService.findCatIdsBySiteId(siteIds, currentCatIndex, max);
	}

	public int countCatBySites(List<String> targets) {
		return siteService.countCatBySites(targets);
	}

	public int countTopicBySites(List<String> targets) {
		return siteService.countTopicBySites(targets);
	}

	public int countContentBySites(List<String> targets) {
		return siteService.countContentBySites(targets);
	}

	public int countSurveyBySites(List<String> targets) {
		return siteService.countSurveyBySites(targets);
	}

	public List<String> findTopicIdsBySiteId(List<String> list,int currentTopicIndex, int max) {
		return topicService.findTopicIdsBySiteId(list, currentTopicIndex, max);
	}

	public List<String> findContentIdsBySiteId(List<String> list,int currentContentIndex, int max) {
		return contentService.findContentIdsBySiteId(list, currentContentIndex, max);
	}

	public List<String> findMoreContentIdsBySiteId(List<String> list,int currentContentIndex, int max) {
		return contentService.findMoreContentIdsBySiteId(list, currentContentIndex, max);
	}

	public List<String> findSurveyIdsBySiteId(List<String> list,int currentSurveryIndex, int max) {
		return surveyService.findSurveyIdsBySiteId(list, currentSurveryIndex, max);
	}

	public int countMoreCatBySites(List<String> targets) {
		return categoryService.countMoreContentByCats(targets);
	}

	public int countMoreTopicBySites(List<String> targets) {
		return topicService.countMoreContentByTopics(targets);
	}

	public int countMoreContentBySites(List<String> targets) {
		return siteService.countMoreContentBySites(targets);
	}

	public List<String> findContentIdsByCatId(List<String> list,int currentContentIndex, int max) {
		return contentService.findContentIdsByCatId(list, currentContentIndex, max);
	}

	public List<String> findMoreContentIdsByCatId(List<String> list,int currentContentIndex, int max) {
		return contentService.findMoreContentIdsByCatId(list, currentContentIndex, max);
	}

	public int countContentByCats(List<String> targets) {
		return categoryService.countContentByCats(targets);
	}

	public int countMoreContentByCats(List<String> targets) {
		return categoryService.countMoreContentByCats(targets);
	}

	public List<String> findContentIdsByTopicId(List<String> list,int currentContentIndex, int max) {
		return contentService.findContentIdsByTopicId(list, currentContentIndex, max);
	}

	public int countContentByTopics(List<String> targets) {
		return topicService.countContentByTopics(targets);
	}

	public int countMoreContentByTopics(List<String> targets) {
		return topicService.countMoreContentByTopics(targets);
	}

	public List<String> findMoreContentIdsByTopicId(List<String> list,int currentContentIndex, int max) {
		return contentService.findMoreContentIdsByTopicId(list, currentContentIndex, max);
	}

	public Site getSite(String siteId) {
		return siteService.getSite(siteId);
	}

	public Category getCategory(String catId) {
		return categoryService.getCategory(catId);
	}

	public String getParentPath(Category obj) {
		return categoryService.getParentPath(obj);
	}

	public List<Content> findAllByPublish(ContentBean contentBean, int pageSize) {
		return contentService.findAllByPublish(contentBean, pageSize);
	}

	public Content getContent(String contentId) {
		return contentService.getContent(contentId);
	}

	public Topic getTopic(String topicId) {
		return topicService.getTopic(topicId);
	}

	public Survey getSurvey(String surveyId) {
		return surveyService.getSurvey(surveyId);
	}

	public Category loadCategory(String catId) {
		return categoryService.loadCategory(catId);
	}

	@Transactional(propagation=Propagation.REQUIRES_NEW)
	public void savePublishLog(PublishLog publishLog) {
		publishLogService.save(publishLog);
	}
	
	@Transactional(propagation=Propagation.REQUIRES_NEW)
	public void savePublishTask(PublishTask publishTask) {
		publishTaskService.save(publishTask);
	}
	
	public void saveContent(Content content,Admin user,String cflag){
		contentService.save(content,user,cflag) ;
	}


}
